home *** CD-ROM | disk | FTP | other *** search
/ Amiga Collections: Franz PD / Franz PD Disk #334 (1994-06)(Rhein-Sieg-Soft).zip / Franz PD Disk #334 (1994-06)(Rhein-Sieg-Soft).adf / ASo-Tools / Sources / Duplicator.c < prev    next >
C/C++ Source or Header  |  1994-04-01  |  7KB  |  263 lines

  1. /* Duplicator.c
  2.  
  3. V1.0 - 15.9.92
  4. V1.1 - 1.4.94: kann unter 1.3 fehlerfrei abbrechen
  5.  
  6. OS2-Utility
  7.  
  8. Aufruf:
  9.  
  10. Duplicator <datei> [...] <verzeichnis>
  11.  
  12. Duplicator kopiert zunächst die genannten Datein ins genannte Verzeichnis.
  13. Danach überwacht er die Dateien mit Notification auf (Schreib-) Zugriffe und
  14. kopiert sie in diesem Falle erneut. Ein gleichzeitiges Umbenennen der
  15. Dateien ist nicht vorgesehen.
  16.  
  17. Duplicator kann durch ^c / Break <n> C abgebrochen werden.
  18.  
  19. Die Größe des Kopierpuffers beträgt BUFFSIZE Bytes. Der Puffer wird nur
  20. für solange alloziert gehalten, wie er benutzt wird.
  21.  
  22. */
  23.  
  24. #define BUFFSIZE 32768
  25.  
  26. #include <exec/memory.h>
  27. #include <exec/ports.h>
  28. #include <dos/dos.h>
  29. #include <dos/dosextens.h>
  30. #include <dos/notify.h>
  31. #include <utility/tagitem.h>
  32. #include <clib/exec_protos.h>
  33. #include <clib/dos_protos.h>
  34. #include <stdlib.h>
  35. #include <string.h>
  36.  
  37. struct ExtNotifyRequest {
  38.             struct ExtNotifyRequest *enr_Next;
  39.             BOOL            enr_NotifyStarted;
  40.             struct NotifyRequest    enr_NotifyRequest;
  41.                };
  42.  
  43. BPTR            OldOut,Out;
  44. struct ExtNotifyRequest *first_enr=NULL;
  45. struct MsgPort        *MyPort=NULL;
  46.  
  47. void CleanUp(void)
  48. {
  49.     struct ExtNotifyRequest *tmp_enr;
  50.     struct Message *msg;
  51.     BPTR myout;
  52.  
  53.     /* Abschied */
  54.     Printf("Duplicator endet"); Flush(Output());
  55.     if(first_enr)
  56.     {
  57.     /* die ExtNotifyRequests sukzessiv freigeben */
  58.     while(tmp_enr=first_enr)
  59.         {
  60.         first_enr=first_enr->enr_Next;
  61.         if(tmp_enr->enr_NotifyStarted)
  62.         EndNotify(&(tmp_enr->enr_NotifyRequest));
  63.         FreeVec(tmp_enr);
  64.         }
  65.     }
  66.     /* ggf. den MsgPort freigeben */
  67.     if(MyPort)  DeleteMsgPort(MyPort);
  68.     /* ggf. Ausgabewindow schließen */
  69.     if(myout=SelectOutput(OldOut))
  70.     {
  71.     Delay(150);
  72.     Close(Out);
  73.     }
  74. }
  75.  
  76. void Error(char *str, void *arg)
  77. { /* Fehlerausstieg */
  78.     Printf(str,arg);
  79.     CleanUp();
  80.     exit(RETURN_ERROR);
  81. }
  82.  
  83. LONG DirEntryType(UBYTE *name)
  84. { /* ermittelt den fib_DirEntryType zum gegebenen Namen, 0-> Fehler */
  85.     BPTR lock;
  86.     struct FileInfoBlock *fib;
  87.     LONG DET=0;
  88.  
  89.     if(lock=Lock(name,ACCESS_READ))
  90.     {
  91.     if(fib=AllocDosObjectTags(DOS_FIB,TAG_END))
  92.         {
  93.         if(Examine(lock,fib))   DET=fib->fib_DirEntryType;
  94.         FreeDosObject(DOS_FIB,fib);
  95.         }
  96.     UnLock(lock);
  97.     }
  98.     return(DET);
  99. }
  100.  
  101. #define IsPath(name) (DirEntryType(name)>0)
  102. #define IsFile(name) (DirEntryType(name)<0)
  103.  
  104. UBYTE *GetENR(UBYTE *name)
  105. { /* wenn möglich, einen ExtNotifyRequest allozieren, den MessagePort
  106.     und Namen eintragen und die Notification starten.
  107.     MyPort muß existieren !
  108.     Ergebnis: der Eintrag nr_FullName/0 bei Fehler */
  109.     struct ExtNotifyRequest *enr;
  110.  
  111.     if(!IsFile(name))
  112.     {
  113.     Printf("%s ist keine (existente) Datei\n",name);
  114.     return(NULL);
  115.     }
  116.     if(!(enr=(struct ExtNotifyRequest *)
  117.          AllocVec(sizeof(struct ExtNotifyRequest),MEMF_CLEAR)))
  118.     {
  119.     Printf("Duplicator kann den Notify-Request zu %s nicht allozieren\n",name);
  120.     return(NULL);
  121.     }
  122.     enr->enr_Next=first_enr;
  123.     first_enr=enr;
  124.     enr->enr_NotifyStarted=FALSE;
  125.     enr->enr_NotifyRequest.nr_Name=name;
  126.     enr->enr_NotifyRequest.nr_stuff.nr_Msg.nr_Port=MyPort;
  127.     enr->enr_NotifyRequest.nr_Flags=NRF_SEND_MESSAGE;
  128.     enr->enr_NotifyStarted=StartNotify(&(enr->enr_NotifyRequest));
  129.     if(!enr->enr_NotifyStarted)
  130.     {
  131.     Printf("Duplicator kann die Notification von %s nicht beginnen\n",name);
  132.     /* Notify-Request freigeben: */
  133.     first_enr=enr->enr_Next;
  134.     FreeVec(enr);
  135.     return(NULL);
  136.     }
  137.     return(enr->enr_NotifyRequest.nr_FullName);
  138. }
  139.  
  140. void Copy(UBYTE *from, UBYTE *to)
  141. { /* Datei des Namens *from nach Pfad *to kopieren */
  142.     UBYTE *toname;
  143.     VOID *FilePuffer;
  144.     int mem_needed;
  145.     BPTR FromFile,ToFile;
  146.     LONG last_read,copied=0;
  147.  
  148.   Printf("Zu kopieren: %s -> %s\n",from,to);
  149.   mem_needed=strlen(from)+strlen(to)+4;
  150.   if(toname=(UBYTE *)AllocVec(mem_needed,MEMF_CLEAR))
  151.     {
  152.     strcpy(toname,to);
  153.     if(AddPart(toname,FilePart(from),mem_needed))
  154.       {
  155.       if(FilePuffer=AllocVec(BUFFSIZE,MEMF_CLEAR))
  156.     {
  157.     if(FromFile=Open(from,MODE_OLDFILE))
  158.       {
  159.       if(ToFile=Open(toname,MODE_NEWFILE))
  160.         {
  161.         do{
  162.           last_read=Read(FromFile,FilePuffer,BUFFSIZE);
  163.           if(last_read==0)  continue;
  164.           if(Write(ToFile,FilePuffer,last_read)!=last_read)
  165.         {
  166.         Printf("Schreibfehler\n");
  167.         last_read=0;
  168.         }
  169.           else copied+=last_read;
  170.           } while(last_read);
  171.         Printf("%ld Bytes von %s nach %s kopiert\n",copied,from,toname);
  172.         Close(ToFile);
  173.         }
  174.       else Printf("Duplicator kann Zieldatei %s nicht öffnen\n",toname);
  175.       Close(FromFile);
  176.       }
  177.     else Printf("Duplicator kann Quelldatei %s nicht öffnen\n",toname);
  178.     FreeVec(FilePuffer);
  179.     }
  180.       else Printf("Duplicator kann Kopierpuffer nicht allozieren\n");
  181.       }
  182.     else Printf("Dos will einen zu langen Dateinamen basteln\n");
  183.     FreeVec(toname);
  184.     }
  185.   else Printf("Duplicator kann Namenspuffer nicht allozieren\n");
  186. }
  187.  
  188. void HandleNotifies(char *todir)
  189. {
  190.     register struct NotifyMessage *msg;
  191.  
  192.     while(msg=(struct NotifyMessage *)GetMsg(MyPort))
  193.     {
  194.     Copy(msg->nm_NReq->nr_FullName,todir);
  195.     ReplyMsg((struct Message *)msg);
  196.     }
  197. }
  198.  
  199. extern struct Library *DOSBase;
  200.  
  201. int main(int argc, char *argv[])
  202. {
  203.     int argcnt;
  204.     UBYTE *thisname;
  205.     LONG GotSigs,ValidSigs;
  206.  
  207.     if(DOSBase->lib_Version<36)
  208.     {
  209.     Write(Output(),"OS2 required\n",13);
  210.     exit(RETURN_FAIL);
  211.     }
  212.  
  213.     /* versuchen, ein Window zu öffnen: [wenn's schiefgeht dennoch
  214.     weitermachen !] */
  215.     OldOut=SelectOutput(Out=
  216.             Open("CON:320/11/320/100/Duplicator",MODE_NEWFILE));
  217.  
  218.     if(argc<3)
  219.     {
  220.     Printf("Aufruf: Duplicator <datei> [...]\n\t\t\t<verzeichnis>\n");
  221.     CleanUp();
  222.     return(RETURN_WARN);
  223.     }
  224.  
  225.     if(!IsPath(argv[argc-1]))
  226.     Error("%s ist kein (existenter) Pfad\n",argv[argc-1]);
  227.     /* Messageport organisieren */
  228.     if(!(MyPort=CreateMsgPort()))
  229.     Error("Duplicator kann seinen MsgPort nicht anlegen\n",NULL);
  230.     /* die Requests anlegen */
  231.     for(argcnt=1;argcnt<argc-1;++argcnt)
  232.     if(thisname=GetENR(argv[argcnt]))
  233.         {
  234.         Copy(thisname,argv[argc-1]);
  235.         Printf("Notification von %s hat begonnen\n",thisname);
  236.         }
  237.  
  238.     if(first_enr)
  239.     {
  240.     /* die relevanten Signale ausfiltern */
  241.     ValidSigs=(SIGBREAKF_CTRL_C | (1<<MyPort->mp_SigBit));
  242.  
  243.     /* auf Abbruch oder Notify-Message warten */
  244.     for(GotSigs=(SetSignal(0,0) & ValidSigs);
  245.         (GotSigs & SIGBREAKF_CTRL_C)==0;
  246.         GotSigs=Wait(ValidSigs)             )
  247.         {
  248.         HandleNotifies(argv[argc-1]);
  249.         if(GotSigs & SIGBREAKF_CTRL_C)  continue;
  250.         while(GotSigs=(SetSignal(0,0) & ValidSigs))
  251.         {
  252.         HandleNotifies(argv[argc-1]);
  253.         if(GotSigs & SIGBREAKF_CTRL_C)  break;
  254.         }
  255.         }
  256.     Printf("^C ... ");  Flush(Output());
  257.     }
  258.     else Printf("Keine der Notifications ist möglich, Sie \23332mRindvieh\23331m !\n");
  259.  
  260.     CleanUp();
  261.     return(RETURN_OK);
  262. }
  263.